#include "Network.h"
#include "Telescope.h"
#include "Controller.h"

Controller * controller_new(char *path) {
	Controller *ct = (Controller *) malloc(sizeof(Controller));
	ct->network = network_new(ct);
	ct->telescope = telescope_new(ct);
	controller_get_settings(ct, path);
	return ct;
}

void controller_get_settings(Controller *controller, char *filename) {
	FILE *file = fopen(filename, "r");
	char line[32], *param;
	while(!feof(file)) {
		if(fgets(line, sizeof(line), file) == NULL)
			break;
		param = strtok(line, "=");
		if(strcmp(param, "connections") == 0)
			sscanf(strtok(NULL, "="), "%"SCNu32, &controller->network->connections);
		else if(strcmp(param, "port") == 0)
			sscanf(strtok(NULL, "="), "%"SCNu16, &controller->network->port);
		else if(strcmp(param, "protocol") == 0)
			sscanf(strtok(NULL, "="), "%"SCNu8, &controller->telescope->protocol);
		else if(strcmp(param, "telescope") == 0)
			sscanf(strtok(NULL, "="), "%s", controller->telescope->path);
	}
	fclose(file);
}

void controller_start(Controller *controller) {
	int e = 0;
	Try {
		network_start(controller->network);
		telescope_start(controller->telescope);
		pthread_mutex_init(&mutex, NULL);
	}
	Catch(e) {
		controller_handle_error(NULL, NULL, e);
	}
}

void controller_stop(Controller *controller) {
	network_stop(controller->network);
	telescope_stop(controller->telescope);
	pthread_mutex_destroy(&mutex);
}

void controller_execute(Controller *controller) {
	network_accept(controller->network);
}

void controller_execute_request(Controller *controller, Client *client, char *message) {
	int e = 500;
	Try {
		if(sizeof(message) > MAX_REQUEST_SIZE)
			Throw e;
		char callback[64], params[32];
		uint8_t command;
		message = strtok(message, "\n");
		int args = sscanf(message, "GET /?callback=%[_0-9a-zA-Z]&u=%"SCNu32"&c=%"SCNu8"+%s HTTP/1.1", callback, &client->id, &command, params);
		if(args == 3 || args == 4) {
			printf("Get data: { args: %d, callback: %s, user_id: %d, command: %d, params: %s }\n", args, callback, client->id, command, params);
			telescope_execute_command(controller->telescope, client, command, params, callback);
		}
		else Throw 1;
	}
	Catch(e) {
		controller_handle_error(controller, client, e);
	}
}

void controller_handle_error(Controller *controller, Client *client, int error) {
	switch(error) {
		case 0:
			perror("ERROR");
			exit(errno);
			break;
		case 1:
			break;
		case 500:
			network_send_error_500(client);
			close(client->socket);
			controller->network->clients = g_list_remove(controller->network->clients, client);
			pthread_cancel(client->thread);
			break;
	}
}
